﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace ConsoleApp1
{
    public class GameManager
    {
        private string[] huaSes = { "Hx", "Ht", "Mh", "Fk" };
        private string[] values = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2" };

        private List<Card> gameCards = new List<Card>(); //游戏牌组
        public List<Player> players = new List<Player>(); //玩家
        private CardsKind cardtype; //出牌类型
        public List<Card> CardInit()
        {
            foreach (var hua in huaSes)
            {
                foreach (var value in values)
                {
                    gameCards.Add(new Card(hua, value));
                }
            }
            gameCards.Add(new Card("", "BK"));
            gameCards.Add(new Card("", "SK"));
            return gameCards;
        }

        /// <summary>
        /// 洗牌
        /// </summary>
        /// <returns>返回洗过的牌</returns>
        public List<Card> ShuffleCards()
        {
            Random rnd = new Random();
            for (int i = gameCards.Count - 1; i > 0; i--)
            {
                var card = gameCards[i];
                int o = rnd.Next(i + 1);
                gameCards[i] = gameCards[o];
                gameCards[o] = card;
            }
            return gameCards;
        }

        /// <summary>
        /// 发牌
        /// </summary>
        public void DealCards()
        {
            var count = players.Count();
            foreach (var player in players)
            {
                var card = gameCards.Take(gameCards.Count / count);
                player.handCards.AddRange(card);
                gameCards.RemoveRange(0, gameCards.Count / count);
                count--;
                player.handCards = CompareHandCards(player.handCards);
            }
        }
        public void AiPlay()
        {
            Random rnd = new Random();
            Player currentPlayer = players[rnd.Next(3)];
            List<Card> outCards = new List<Card>();
            List<Card> preCards = new List<Card>(); //上一个玩家的出牌
            Player? prePlayer = null;

            int i = rnd.Next(3);
            try
            {
                //后续轮次
                do
                {
                    outCards.Clear();
                    if (i > 2) i = i % 3;
                    currentPlayer = players[i];

                    Console.WriteLine($" {currentPlayer.name} 回合：");
                    if (preCards.Count != 0 && currentPlayer == prePlayer) preCards.Clear();
                    if (preCards.Count != 0 && !HaveCardsEnoughBigger(currentPlayer.handCards, preCards))
                    {
                        Console.WriteLine("---不出\n");
                        i++;
                        continue;
                    }
                    Console.Write("---打出：");

                    switch (cardtype)
                    {
                        case CardsKind.noCards:
                        case CardsKind.doubleCard:
                            if (preCards.Count != 0)
                            {
                                outCards = GetMinDoubleCards(currentPlayer.handCards, preCards);
                            }
                            else outCards = GetMinDoubleCards(currentPlayer.handCards);
                            if (preCards != null && preCards.Count == 0 && outCards.Count == 1)//说明牌内无对子
                            {
                                //outCards.Add(GetMinSingleCard(currentPlayer.handCards));
                                goto case CardsKind.singleCard;
                            }
                            cardtype = CardsKind.doubleCard;
                            break;
                        case CardsKind.singleCard:
                            outCards.Add(GetMinSingleCard(currentPlayer.handCards, preCards));
                            cardtype = CardsKind.singleCard;
                            break;
                        default:
                            Console.WriteLine("牌型出错");
                            break;
                    }
                    preCards!.Clear();
                    string outCardStr = JsonConvert.SerializeObject(outCards);
                    List<Card> newCard = JsonConvert.DeserializeObject<List<Card>>(outCardStr)!;
                    preCards.AddRange(newCard);
                    prePlayer = currentPlayer;

                    foreach (var card in outCards)
                    {
                        card.PrintCards();
                        currentPlayer.handCards.Remove(card);
                    }
                    Console.WriteLine();
                    if (currentPlayer.handCards.Count == 0)
                    {
                        Console.WriteLine($"游戏结束， {currentPlayer.name} 胜利");
                        return;
                    }
                    i++;
                    Console.WriteLine();

                } while (true);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                Console.ReadKey();
            }
            
        }

        /// <summary>
        /// 获取最小的对子
        /// </summary>
        /// <param name="cards">传入的玩家牌组</param>
        /// <param name="preCard">上个玩家出的牌（可无）</param>
        /// <returns>返回对子</returns>
        private List<Card> GetMinDoubleCards(List<Card> cards, List<Card>? preCard = null)
        {
            List<Card> minCards = new List<Card>();
            string cardStr = JsonConvert.SerializeObject(preCard);

            if (preCard != null)
                minCards = JsonConvert.DeserializeObject<List<Card>>(cardStr)!;
            else minCards.Add(new Card("", "0"));

            for (int i = 0; i < cards.Count - 1; i++)
            {
                if (preCard != null && preCard.Count != 0)
                {
                    while (i < cards.Count - 1 && GetCardValue(preCard[0]) > GetCardValue(cards[i]))
                    {
                        i++;
                    }
                }
                if (cards[i].value == cards[i + 1].value &&
                     GetCardValue(minCards[0]) < GetCardValue(cards[i]))
                {
                    minCards.Clear();
                    minCards.Add(cards[i]);
                    minCards.Add(cards[i + 1]);
                    break;
                }
            }
            return minCards;
        }

        /// <summary>
        /// 获取最小的单牌
        /// </summary>
        /// <param name="cards">传入的牌组</param>
        /// <param name="preCard">上个玩家出的牌</param>
        /// <returns>返回单张牌</returns>
        private Card GetMinSingleCard(List<Card> cards, List<Card>? preCard = null)
        {
            Card minCards = new Card("", "0");
            if (preCard != null&&preCard.Count!=0)
            {
                string cardStr = JsonConvert.SerializeObject(preCard[0]);
                minCards = JsonConvert.DeserializeObject<Card>(cardStr)!;
            }
            for (int i = 0; i < cards.Count; i++)
            {
                if (preCard != null && preCard.Count != 0)
                {
                    while (i < cards.Count - 1 && GetCardValue(preCard[0]) > GetCardValue(cards[i])) 
                        i++;
                }
                if (GetCardValue(minCards) < GetCardValue(cards[i]))
                {
                    minCards = cards[i];
                    break;
                }
            }
            return minCards;
        }

        /// <summary>
        /// 卡牌排序
        /// </summary>
        /// <param name="cards"></param>
        /// <returns>排好的牌</returns>
        private List<Card> CompareHandCards(List<Card> cards)
        {
            Card temCard = new Card();
            for (int i = 0; i < cards.Count; i++)
            {
                for (int j = i; j > 0; j--)
                {
                    if (GetCardValue(cards[j]) < GetCardValue(cards[j - 1]))
                    {
                        temCard = cards[j];
                        cards[j] = cards[j - 1];
                        cards[j - 1] = temCard;
                    }
                }
            }
            return cards;
        }

        /// <summary>
        /// 手牌里是否有比上个玩家大的牌
        /// </summary>
        /// <param name="cards">玩家手牌</param>
        /// <param name="value">上个玩家打出牌的大小</param>
        /// <returns>True-有大牌，False-无大牌</returns>
        private bool HaveCardsEnoughBigger(List<Card> cards, List<Card> preCards)
        {
            switch (cardtype)
            {
                case CardsKind.doubleCard:
                    //对子
                    List<Card> maxCards = new List<Card>();
                    maxCards.Add(new Card("", "0"));
                    for (int i = cards.Count - 1; i > 0; i--)
                    {
                        if (cards[i].value == cards[i - 1].value)
                        {
                            maxCards.Clear();
                            maxCards.Add(cards[i]);
                            maxCards.Add(cards[i - 1]);
                            break;
                        }
                    }
                    if (GetCardValue(maxCards[0]) > GetCardValue(preCards[0]))
                    {
                        return true;
                    }
                    else return false;
                case CardsKind.singleCard:
                    if (GetCardValue(cards[cards.Count - 1]) > GetCardValue(preCards[0]))
                    {
                        return true;
                    }
                    else return false;
                default:
                    return false;
            }

        }

        /// <summary>
        /// 获取卡牌大小
        /// </summary>
        /// <param name="card"></param>
        /// <returns>返回大小数值</returns>
        private int GetCardValue(Card card)
        {
            Dictionary<string, int> cardValue = new Dictionary<string, int>
            {
                { "0",0},{ "3",1},{ "4",2},{ "5",3},{ "6",4},{ "7",5},{ "8",6},{ "9",7},{ "10",8},
                { "J",9},{ "Q",10},{ "K",11},{ "A",12},{ "2",13},{ "SK",14},{ "BK",15}
            };
            if (card.value != null)
            {
                return cardValue.ContainsKey(card.value) ? cardValue[card.value] : 0;
            }
            return 0;
        }

        /// <summary>
        /// 获取卡牌的类型（单牌、对子）
        /// </summary>
        /// <param name="Card">需判断的牌组</param>
        /// <returns>返回单牌或对子，错误时返回errorType</returns>
        private CardsKind GetCardsType(List<Card> Card)
        {
            if (isSingleCard(Card))
                return CardsKind.singleCard;
            if (isDoubleCard(Card))
                return CardsKind.doubleCard;
            else
                return CardsKind.errorType;
        }
        private bool isSingleCard(List<Card> Card)
        {
            if (Card.Count == 1)
                return true;
            else
                return false;
        }
        private bool isDoubleCard(List<Card> Cards)
        {
            if (Cards.Count == 2 && Cards[0].value == Cards[1].value)
                return true;
            else
                return false;
        }
    }
}
